#ifndef __SCENELOADER_H_INCLUDED__
#define __SCENELOADER_H_INCLUDED__

// Includes
#include <OgreString.h>
#include <OgreVector3.h>
#include <OgreQuaternion.h>
#include <vector>

// Forward declarations
class TiXmlElement;
using namespace Ogre;

namespace Ogre
{
    // Forward declarations
	class SceneManager;
	class SceneNode;
}

namespace RockyRay
{

    /// Callback class used to deal with user data
    class ISceneCallback
    {
    public:
        virtual void ProcessEntityData(SceneNode *pParent, Entity *pEntity, 
            String data) = 0;
        virtual void ProcessNodeData(SceneNode *pParent, String data) = 0;
    };

	class nodeProperty
	{
	public:
        ///name of the node
		String name;
		String value;

        ///Create a new nodeProperty and fill its fields
		nodeProperty(const String &Name, const String &Value)
            : name(Name), value(Value){};
	};

    class ISceneLoader
    {
    public:
        virtual ~ISceneLoader(){};
        virtual void parseDotScene(const String &SceneName, 
            const String &groupName, SceneManager *yourSceneMgr, 
            SceneNode *pAttachNode = NULL, const String &sPrependNode = "") = 0;
		virtual String getProperty(const String &ndNm, const String &prop) = 0;
    };

    ///Loader deals with the dotscene format
    class DotSceneLoader : public ISceneLoader
	{
	public:
		DotSceneLoader() : mSceneMgr(0) { udCallback = NULL; }
		virtual ~DotSceneLoader() {}

        /// Load the scene
        /** @param SceneName file name of the scene file.
            @param groupName groupName for scene manager
            @param yourSceneMgr pointer to the SceneMgr
            @param pAttachNode where the scene attached to
            @param sPrependNode what does this mean? */
		void parseDotScene(const String &SceneName, const String &groupName, 
            SceneManager *yourSceneMgr, SceneNode *pAttachNode = NULL, 
            const String &sPrependNode = "");
		String getProperty(const String &ndNm, const String &prop);

        /// Register a user data callback class
        void RegisterSceneCallback(ISceneCallback* callback);

		std::vector<nodeProperty> nodeProperties;
		std::vector<String> staticObjects;
		std::vector<String> dynamicObjects;

	protected:
		void processScene(TiXmlElement *XMLRoot);

		void processNodes(TiXmlElement *XMLNode);
		void processExternals(TiXmlElement *XMLNode);
		void processEnvironment(TiXmlElement *XMLNode);
		void processTerrain(TiXmlElement *XMLNode);
		void processUserDataReference(TiXmlElement *XMLNode, SceneNode *pParent = 0);
		void processUserDataReference(TiXmlElement *XMLNode, Entity *pEntity, SceneNode *pParent);
		void processOctree(TiXmlElement *XMLNode);
		void processLight(TiXmlElement *XMLNode, SceneNode *pParent = 0);
		void processCamera(TiXmlElement *XMLNode, SceneNode *pParent = 0);

        /// return false if its skiping next node
		bool processNode(TiXmlElement *XMLNode, SceneNode *pParent = 0);
		void processLookTarget(TiXmlElement *XMLNode, SceneNode *pParent);
		void processTrackTarget(TiXmlElement *XMLNode, SceneNode *pParent);
		void processEntity(TiXmlElement *XMLNode, SceneNode *pParent);
		void processParticleSystem(TiXmlElement *XMLNode, SceneNode *pParent);
		void processBillboardSet(TiXmlElement *XMLNode, SceneNode *pParent);
		void processPlane(TiXmlElement *XMLNode, SceneNode *pParent);

		void processFog(TiXmlElement *XMLNode);
		void processSkyBox(TiXmlElement *XMLNode);
		void processSkyDome(TiXmlElement *XMLNode);
		void processSkyPlane(TiXmlElement *XMLNode);
		void processClipping(TiXmlElement *XMLNode);

		void processLightRange(TiXmlElement *XMLNode, Light *pLight);
		void processLightAttenuation(TiXmlElement *XMLNode, Light *pLight);

		String getAttrib(TiXmlElement *XMLNode, const String &parameter, 
            const String &defaultValue = "");
		Real getAttribReal(TiXmlElement *XMLNode, const String &parameter, 
            Real defaultValue = 0);
		bool getAttribBool(TiXmlElement *XMLNode, const String &parameter, 
            bool defaultValue = false);

		Vector3 parseVector3(TiXmlElement *XMLNode);
		Quaternion parseQuaternion(TiXmlElement *XMLNode);
		ColourValue parseColour(TiXmlElement *XMLNode);
		

		SceneManager *mSceneMgr;
		SceneNode *mAttachNode;
		String m_sGroupName;
		String m_sPrependNode;
        ISceneCallback *udCallback;
	};
}

#endif